#include "tcpconnection.hpp"
#include <sstream>
#include "logger.h"
namespace moqi
{
    TcpConnection::TcpConnection(int fd, EventLoop *loop)
        : _sock(fd),
          _sockio(fd),
          _localAddr(getLocalAddr()),
          _peerAddr(getPeerAddr()),
          _loop(loop),
          _lastActiveTime(time(NULL))
    {
    }
    TcpConnection::~TcpConnection()
    {
    }

    void TcpConnection::send(const string &msg)
    {
        LOG_INFO("send " + msg + status());
        _sockio.sendn(msg.c_str(), msg.size());
    }

    int TcpConnection::readPacket(Packet &mes)
    {
        return _sockio.readPacket(mes);
    }
    void TcpConnection::sendInloop(const string &msg)
    {
        LOG_INFO("TcpConnection::sendInloop(const string & msg)");
        if (_loop)
        {
            _loop->sendInLoop(std::bind(&TcpConnection::send, this, msg));
        }
    }
    void TcpConnection::sendInloop(const TLV &tlv)
    {
        LOG_INFO("TcpConnection::sendInloop(const TLV& msg)");
        if (_loop)
        {
            std::ostringstream oss;
            oss << tlv.type << tlv.length << tlv.msg;
            _loop->sendInLoop(std::bind(&TcpConnection::send, this, oss.str()));
        }
    }
    string TcpConnection::receive()
    {
        LOG_INFO("recv");
        char buff[65536] = {0};
        int ret = _sockio.recvLine(buff, sizeof(buff));
        LOG_INFO("\n recv msg's size: %d\n", ret);
        return string(buff, ret);
    }

    void TcpConnection::shutdown()
    {
        LOG_INFO("shutdown");
        _sock.shutdownWrite();
    }

    bool TcpConnection::isClosed() const
    {
        char buff[20] = {0};
        return _sockio.recvPeek(buff, sizeof(buff)) == 0;
    }

    string TcpConnection::status() const
    {
        std::ostringstream oss;
        oss << "[ " << _localAddr.ip() << " : " << _localAddr.port() << " ---> "
            << _peerAddr.ip() << " : " << _peerAddr.port() << " ]";
        return oss.str();
    }

    void TcpConnection::handleConnectionCallback()
    {
        if (_onConnecton)
        {
            _onConnecton(shared_from_this());
        }
    }

    void TcpConnection::handleMessageCallback()
    {
        if (_onMessage)
        {
            _onMessage(shared_from_this());
        }
    }

    void TcpConnection::handleCloseCallback()
    {
        if (_onClose)
        {
            _onClose(shared_from_this());
        }
    }
    void TcpConnection::updateActiveTime()
    {
        _lastActiveTime = time(nullptr);
    }

    bool TcpConnection::checkTimeOut(int maxInavtiveTime)
    {
        time_t curTime = time(nullptr);
        if (curTime - _lastActiveTime > maxInavtiveTime)
        {
            LOG_INFO("%ld, %ld",curTime,_lastActiveTime);
            return true; // 查看是否超时
        }
        return false;
    }

    InetAddress TcpConnection::getLocalAddr()
    {
        address_IPv4 addr;
        socklen_t len = sizeof(addr);
        memset(&addr, 0, len);
        int ret = getpeername(_sock.fd(), (struct sockaddr *)&addr, &len);
        if (ret < 0)
        {
            LOG_ERROR("getLocalAddr");
        }
        return InetAddress(addr);
    }

    InetAddress TcpConnection::getPeerAddr()
    {
        address_IPv4 addr;
        socklen_t len = sizeof(addr);
        memset(&addr, 0, len);
        int ret = getsockname(_sock.fd(), (struct sockaddr *)&addr, &len);
        if (ret < 0)
        {
            LOG_ERROR("getPeerAddr");
        }
        return InetAddress(addr);
    }

} // end of namespace moqi
